

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/my-blog-template/assets/img/cxy.png">
  <link rel="icon" href="/my-blog-template/assets/img/cxy.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">

  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="CV Man">
  <meta name="keywords" content="">

    <meta name="description" content="Vue初始化过程源码理解">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue源码理解-初始化">
<meta property="og:url" content="https://jiachengh.gitee.io/my-blog-template/2022/01/28/Vue-source-code-init/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="Vue初始化过程源码理解">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://jiachengh.gitee.io/my-blog-template/my-blog-template/2022/01/28/Vue-source-code-init/assets/img/vueSourceCode/init/1.jpg">
<meta property="og:image" content="https://jiachengh.gitee.io/my-blog-template/my-blog-template/2022/01/28/Vue-source-code-init/assets/img/vueSourceCode/init/2.jpg">
<meta property="og:image" content="https://jiachengh.gitee.io/my-blog-template/my-blog-template/2022/01/28/Vue-source-code-init/assets/img/vueSourceCode/init/3.jpg">
<meta property="article:published_time" content="2022-01-28T11:30:22.000Z">
<meta property="article:modified_time" content="2023-05-12T15:53:19.166Z">
<meta property="article:author" content="CV Man">
<meta property="article:tag" content="学习">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://jiachengh.gitee.io/my-blog-template/my-blog-template/2022/01/28/Vue-source-code-init/assets/img/vueSourceCode/init/1.jpg">



  <title>Vue源码理解-初始化 - Hexo</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/my-blog-template/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/my-blog-template/css/highlight.css" />

    <link id="highlight-css-dark" rel="stylesheet" href="/my-blog-template/css/highlight-dark.css" />





<link rel="stylesheet" href="/my-blog-template/assets/css/common.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"jiachengh.gitee.io","root":"/my-blog-template/","version":"1.9.4","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/my-blog-template/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/my-blog-template/js/utils.js" ></script>
  <script  src="/my-blog-template/js/color-schema.js" ></script>




<meta name="generator" content="Hexo 6.3.0"></head>


<body>


  <header>


<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/my-blog-template/">
      <strong>CV Man&#39;s Blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">





            <li class="nav-item">
              <a class="nav-link" href="/my-blog-template/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>






            <li class="nav-item">
              <a class="nav-link" href="/my-blog-template/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>






            <li class="nav-item">
              <a class="nav-link" href="/my-blog-template/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>






            <li class="nav-item">
              <a class="nav-link" href="/my-blog-template/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>






            <li class="nav-item">
              <a class="nav-link" href="/my-blog-template/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>



          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>



          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>

      </ul>
    </div>
  </div>
</nav>



<div id="banner" class="banner" parallax=true
     style="background: url('/my-blog-template/assets/img/banner.jpeg') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">

            <span id="subtitle" data-typed-text="Vue源码理解-初始化"></span>

        </div>



  <div class="mt-3">


      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-01-28 19:30" pubdate>
          2022年1月28日 晚上
        </time>
      </span>

  </div>

  <div class="mt-1">

      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>

          20k 字

      </span>



      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>



          165 分钟

      </span>




  </div>



      </div>


    </div>
  </div>
</div>

</div>

  </header>

  <main>



<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Vue源码理解-初始化</h1>


              <div class="markdown-body">

                <h1 id="从-new-Vue-options-开始"><a href="#从-new-Vue-options-开始" class="headerlink" title="从 new Vue(options)开始"></a>从 new Vue(options)开始</h1><h1 id="首先找到-Vue-的构造函数"><a href="#首先找到-Vue-的构造函数" class="headerlink" title="首先找到 Vue 的构造函数"></a>首先找到 Vue 的构造函数</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;index.js<br><img src="/my-blog-template/assets/img/vueSourceCode/init/1.jpg" srcset="/my-blog-template/img/loading.gif" lazyload><br>可以看到 Vue 构造函数中调用了 Vue.prototype_init 方法，该方法在 initMixin 中定义，接着去 init 文件中找到该方法。</p>
</blockquote>
<h1 id="Vue-prototype-init"><a href="#Vue-prototype-init" class="headerlink" title="Vue.prototype_init"></a>Vue.prototype_init</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;init.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initMixin</span> (<span class="hljs-title class_">Vue</span>: <span class="hljs-title class_">Class</span>&lt;<span class="hljs-title class_">Component</span>&gt;) &#123;<br>  <span class="hljs-title class_">Vue</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">_init</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">options?: <span class="hljs-built_in">Object</span></span>) &#123;<br>    <span class="hljs-comment">// vue 实例</span><br>    <span class="hljs-keyword">const</span> <span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span> = <span class="hljs-variable language_">this</span><br>    <span class="hljs-comment">// 每个vue实例都有一个uid，并且递增</span><br>    vm.<span class="hljs-property">_uid</span> = uid++<br><br>    <span class="hljs-keyword">let</span> startTag, endTag<br>    <span class="hljs-comment">/* istanbul ignore if */</span><br>    <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span> &amp;&amp; config.<span class="hljs-property">performance</span><br>    &amp;&amp; mark)<br>    &#123;<br>      startTag = <span class="hljs-string">`vue-perf-start:<span class="hljs-subst">$&#123;vm._uid&#125;</span>`</span><br>      endTag = <span class="hljs-string">`vue-perf-end:<span class="hljs-subst">$&#123;vm._uid&#125;</span>`</span><br>      <span class="hljs-title function_">mark</span>(startTag)<br>    &#125;<br><br>    <span class="hljs-comment">// a flag to avoid this being observed</span><br>    vm.<span class="hljs-property">_isVue</span> = <span class="hljs-literal">true</span><br>    <span class="hljs-comment">// merge options</span><br>    <span class="hljs-keyword">if</span> (options &amp;&amp; options.<span class="hljs-property">_isComponent</span>) &#123;<br>      <span class="hljs-comment">// 子组件初始化走这边</span><br>      <span class="hljs-title function_">initInternalComponent</span>(vm, options)<br>    &#125; <span class="hljs-keyword">else</span> &#123;<br>      <span class="hljs-comment">// 根组件初始化走这边</span><br>      vm.<span class="hljs-property">$options</span> = <span class="hljs-title function_">mergeOptions</span>(<br>        <span class="hljs-title function_">resolveConstructorOptions</span>(vm.<span class="hljs-property">constructor</span>),<br>        options || &#123;&#125;,<br>        vm<br>      )<br>    &#125;<br>    <span class="hljs-comment">// 设置代理，将vm实例上的属性代理到vm._renderProxy上</span><br>    <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span>) &#123;<br>      <span class="hljs-title function_">initProxy</span>(vm)<br>    &#125; <span class="hljs-keyword">else</span> &#123;<br>      vm.<span class="hljs-property">_renderProxy</span> = vm<br>    &#125;<br>    <span class="hljs-comment">// expose real self</span><br>    vm.<span class="hljs-property">_self</span> = vm<br>    <span class="hljs-comment">// 初始化组件实例关系属性，比如 $parent、$children、$root、$refs 等</span><br>    <span class="hljs-title function_">initLifecycle</span>(vm)<br>    <span class="hljs-comment">// 初始化自定义事件</span><br>    <span class="hljs-title function_">initEvents</span>(vm)<br>    <span class="hljs-comment">/* 解析组件的插槽信息，得到vm.$slot</span><br><span class="hljs-comment">    处理渲染函数，得到vm.$createElement方法，即h函数 */</span><br>    <span class="hljs-title function_">initRender</span>(vm)<br>    <span class="hljs-comment">// 调用beforeCreate钩子函数</span><br>    <span class="hljs-title function_">callHook</span>(vm, <span class="hljs-string">&#x27;beforeCreate&#x27;</span>)<br>    <span class="hljs-comment">/* 初始化组件的inject配置项得到 result[key] = val 形式的配置对象，</span><br><span class="hljs-comment">    然后对结果数据进行响应式处理，并代理每个 key 到 vm 实例 */</span><br>    <span class="hljs-title function_">initInjections</span>(vm) <span class="hljs-comment">// resolve injections before data/props</span><br>    <span class="hljs-comment">// 数据响应式的重点，处理props methods data computed watch</span><br>    <span class="hljs-title function_">initState</span>(vm)<br>    <span class="hljs-comment">// 解析组件上的provide对象，挂载到vm._provide属性上</span><br>    <span class="hljs-title function_">initProvide</span>(vm) <span class="hljs-comment">// resolve provide after data/props</span><br>    <span class="hljs-comment">// 调用钩子函数created</span><br>    <span class="hljs-title function_">callHook</span>(vm, <span class="hljs-string">&#x27;created&#x27;</span>)<br><br>    <span class="hljs-comment">/* istanbul ignore if */</span><br>    <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span> &amp;&amp; config.<span class="hljs-property">performance</span><br>    &amp;&amp; mark)<br>    &#123;<br>      vm.<span class="hljs-property">_name</span> = <span class="hljs-title function_">formatComponentName</span>(vm, <span class="hljs-literal">false</span>)<br>      <span class="hljs-title function_">mark</span>(endTag)<br>      <span class="hljs-title function_">measure</span>(<span class="hljs-string">`vue <span class="hljs-subst">$&#123;vm._name&#125;</span> init`</span>, startTag, endTag)<br>    &#125;<br><br>    <span class="hljs-keyword">if</span> (vm.<span class="hljs-property">$options</span>.<span class="hljs-property">el</span>) &#123;<br>      vm.$mount(vm.<span class="hljs-property">$options</span>.<span class="hljs-property">el</span>)<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="initInternalComponent"><a href="#initInternalComponent" class="headerlink" title="initInternalComponent"></a>initInternalComponent</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;init.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initInternalComponent</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>, <span class="hljs-attr">options</span>: <span class="hljs-title class_">InternalComponentOptions</span>) &#123;<br>  <span class="hljs-comment">// 基于组件构造函数上的配置对象生成vm.$options</span><br>  <span class="hljs-keyword">const</span> opts = vm.<span class="hljs-property">$options</span> = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(vm.<span class="hljs-property">constructor</span>.<span class="hljs-property">options</span>)<br>  <span class="hljs-comment">// doing this because it&#x27;s faster than dynamic enumeration.</span><br>  <span class="hljs-keyword">const</span> parentVnode = options.<span class="hljs-property">_parentVnode</span><br>  opts.<span class="hljs-property">parent</span> = options.<span class="hljs-property">parent</span><br>  opts.<span class="hljs-property">_parentVnode</span> = parentVnode<br><br>  <span class="hljs-comment">// 把组件传进来的一些配置赋值到vm.$options上</span><br>  <span class="hljs-keyword">const</span> vnodeComponentOptions = parentVnode.<span class="hljs-property">componentOptions</span><br>  opts.<span class="hljs-property">propsData</span> = vnodeComponentOptions.<span class="hljs-property">propsData</span><br>  opts.<span class="hljs-property">_parentListeners</span> = vnodeComponentOptions.<span class="hljs-property">listeners</span><br>  opts.<span class="hljs-property">_renderChildren</span> = vnodeComponentOptions.<span class="hljs-property">children</span><br>  opts.<span class="hljs-property">_componentTag</span> = vnodeComponentOptions.<span class="hljs-property">tag</span><br>  <span class="hljs-comment">// 如果有render函数，将其赋值到vm.$options上</span><br>  <span class="hljs-keyword">if</span> (options.<span class="hljs-property">render</span>) &#123;<br>    opts.<span class="hljs-property">render</span> = options.<span class="hljs-property">render</span><br>    opts.<span class="hljs-property">staticRenderFns</span> = options.<span class="hljs-property">staticRenderFns</span><br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="resolveConstructorOptions"><a href="#resolveConstructorOptions" class="headerlink" title="resolveConstructorOptions"></a>resolveConstructorOptions</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;init.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-comment">// 从组件构造函数中解析配置对象options并合并基类选项</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">resolveConstructorOptions</span> (<span class="hljs-title class_">Ctor</span>: <span class="hljs-title class_">Class</span>&lt;<span class="hljs-title class_">Component</span>&gt;) &#123;<br>  <span class="hljs-comment">/*</span><br><span class="hljs-comment">    Ctor是基础Vue构造器，直接返回options</span><br><span class="hljs-comment">    Vue构造函数上的options，如directives,filters</span><br><span class="hljs-comment">    Vue构造函数上的options定义主要在两个文件</span><br><span class="hljs-comment">      /src/platforms/web/runtime/index.js中给Vue.options.directives</span><br><span class="hljs-comment">      添加model和show属性，给components添加transition和</span><br><span class="hljs-comment">      transition-group属性</span><br><span class="hljs-comment">      /src/core/global-api/index.js中给Vue.options添加filters,_base,</span><br><span class="hljs-comment">      以及components中的keepAlive</span><br><span class="hljs-comment">      这些就是Vue构造函数的options</span><br><span class="hljs-comment">  */</span><br>  <span class="hljs-keyword">let</span> options = <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">options</span><br>  <span class="hljs-comment">// 有super属性，说明Ctor是Vue.extend构建的子类</span><br>  <span class="hljs-keyword">if</span> (<span class="hljs-title class_">Ctor</span>.<span class="hljs-property">super</span>) &#123;<br>    <span class="hljs-comment">/*</span><br><span class="hljs-comment">      Ctor.super是Vue.extend构建子类的时候，为Ctor添加一个super属性，指向</span><br><span class="hljs-comment">      其父类构造器</span><br><span class="hljs-comment">      有super属性，则递归解析父类构造函数的选项</span><br><span class="hljs-comment">      superOptions 基类的options</span><br><span class="hljs-comment">      cachedSuperOptions 自身的options</span><br><span class="hljs-comment">    */</span><br>    <span class="hljs-keyword">const</span> superOptions = <span class="hljs-title function_">resolveConstructorOptions</span>(<span class="hljs-title class_">Ctor</span>.<span class="hljs-property">super</span>)<br>    <span class="hljs-keyword">const</span> cachedSuperOptions = <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">superOptions</span><br>    <span class="hljs-keyword">if</span> (superOptions !== cachedSuperOptions) &#123;<br>      <span class="hljs-comment">// 如果基类的options发生了改变，则需要重新设置自身的options</span><br>      <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">superOptions</span> = superOptions<br>      <span class="hljs-comment">// check if there are any late-modified/attached options (#4976)</span><br>      <span class="hljs-comment">// 检查 Ctor.options上是否有任何后期修改/附加的选项</span><br>      <span class="hljs-keyword">const</span> modifiedOptions = <span class="hljs-title function_">resolveModifiedOptions</span>(<span class="hljs-title class_">Ctor</span>)<br>      <span class="hljs-comment">/*</span><br><span class="hljs-comment">        如果存在被修改或增加的选项，则将改变的选项modifiedOptions合并到</span><br><span class="hljs-comment">        自身的extendOptions</span><br><span class="hljs-comment">      */</span><br>      <span class="hljs-keyword">if</span> (modifiedOptions) &#123;<br>        <span class="hljs-title function_">extend</span>(<span class="hljs-title class_">Ctor</span>.<span class="hljs-property">extendOptions</span>, modifiedOptions)<br>      &#125;<br>      <span class="hljs-comment">// options合并，将改变的选项与自身的选项合并结果并赋值为Ctor.options</span><br>      options =<br>        <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">options</span> = <span class="hljs-title function_">mergeOptions</span>(superOptions, <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">extendOptions</span>)<br>      <span class="hljs-keyword">if</span> (options.<span class="hljs-property">name</span>) &#123;<br>        options.<span class="hljs-property">components</span>[options.<span class="hljs-property">name</span>] = <span class="hljs-title class_">Ctor</span><br>      &#125;<br>    &#125;<br>  &#125;<br>  <span class="hljs-keyword">return</span> options<br>&#125;<br></code></pre></td></tr></table></figure>

<p>resolveConstructorOptions 的流程图<br><img src="/my-blog-template/assets/img/vueSourceCode/init/2.jpg" srcset="/my-blog-template/img/loading.gif" lazyload></p>
<h1 id="resolveModifiedOptions"><a href="#resolveModifiedOptions" class="headerlink" title="resolveModifiedOptions"></a>resolveModifiedOptions</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;init.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">resolveModifiedOptions</span> (<span class="hljs-title class_">Ctor</span>: <span class="hljs-title class_">Class</span>&lt;<span class="hljs-title class_">Component</span>&gt;): ?<span class="hljs-title class_">Object</span> &#123;<br>  <span class="hljs-keyword">let</span> modified<br>  <span class="hljs-keyword">const</span> latest = <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">options</span><br>  <span class="hljs-keyword">const</span> sealed = <span class="hljs-title class_">Ctor</span>.<span class="hljs-property">sealedOptions</span><br>  <span class="hljs-comment">// 对比两个选项，记录不一样的选项</span><br>  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> key <span class="hljs-keyword">in</span> latest) &#123;<br>    <span class="hljs-keyword">if</span> (latest[key] !== sealed[key]) &#123;<br>      <span class="hljs-keyword">if</span> (!modified) modified = &#123;&#125;<br>      modified[key] = latest[key]<br>    &#125;<br>  &#125;<br>  <span class="hljs-keyword">return</span> modified<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="mergeOptions"><a href="#mergeOptions" class="headerlink" title="mergeOptions"></a>mergeOptions</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;util&#x2F;options.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-comment">/*</span><br><span class="hljs-comment">  参数parent 该实例构造函数的options</span><br><span class="hljs-comment">  child 该实例的options</span><br><span class="hljs-comment">  vm 该实例本身</span><br><span class="hljs-comment">*/</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">mergeOptions</span> (<br>  <span class="hljs-attr">parent</span>: <span class="hljs-title class_">Object</span>,<br>  <span class="hljs-attr">child</span>: <span class="hljs-title class_">Object</span>,<br>  vm?: <span class="hljs-title class_">Component</span><br>  ): <span class="hljs-title class_">Object</span> &#123;<br>  <span class="hljs-comment">// 如果不是生产环境，检查组件的命名是否合法</span><br>  <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span>) &#123;<br>    <span class="hljs-title function_">checkComponents</span>(child)<br>  &#125;<br>  <span class="hljs-comment">// 如果child是函数。则取其options作为child</span><br>  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> child === <span class="hljs-string">&#x27;function&#x27;</span>) &#123;<br>    child = child.<span class="hljs-property">options</span><br>  &#125;<br><br>  <span class="hljs-comment">// 将options中的props inject directives转换为对象的形式</span><br>  <span class="hljs-title function_">normalizeProps</span>(child, vm)<br>  <span class="hljs-title function_">normalizeInject</span>(child, vm)<br>  <span class="hljs-title function_">normalizeDirectives</span>(child)<br><br>  <span class="hljs-comment">// Apply extends and mixins on the child options,</span><br>  <span class="hljs-comment">// but only if it is a raw options object that isn&#x27;t</span><br>  <span class="hljs-comment">// the result of another mergeOptions call.</span><br>  <span class="hljs-comment">// Only merged options has the _base property.</span><br>  <span class="hljs-comment">/*</span><br><span class="hljs-comment">    经过mergeOptions处理过的child会有_base属性，如果处理过了，则不用再处理</span><br><span class="hljs-comment">    如果该实例的options(child)有extends和mixins属性，则将这两个属性合并到</span><br><span class="hljs-comment">    该实例的构造函数（parent）上</span><br><span class="hljs-comment">  */</span><br>  <span class="hljs-keyword">if</span> (!child.<span class="hljs-property">_base</span>) &#123;<br>    <span class="hljs-keyword">if</span> (child.<span class="hljs-property">extends</span>) &#123;<br>      parent = <span class="hljs-title function_">mergeOptions</span>(parent, child.<span class="hljs-property">extends</span>, vm)<br>    &#125;<br>    <span class="hljs-keyword">if</span> (child.<span class="hljs-property">mixins</span>) &#123;<br>      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>, l = child.<span class="hljs-property">mixins</span>.<span class="hljs-property">length</span>; i &lt; l; i++) &#123;<br>        parent = <span class="hljs-title function_">mergeOptions</span>(parent, child.<span class="hljs-property">mixins</span>[i], vm)<br>      &#125;<br>    &#125;<br>  &#125;<br>  <span class="hljs-comment">// options存放合并之后的options</span><br>  <span class="hljs-keyword">const</span> options = &#123;&#125;<br>  <span class="hljs-keyword">let</span> key<br>  <span class="hljs-keyword">for</span> (key <span class="hljs-keyword">in</span> parent) &#123;<br>    <span class="hljs-title function_">mergeField</span>(key)<br>  &#125;<br>  <span class="hljs-keyword">for</span> (key <span class="hljs-keyword">in</span> child) &#123;<br>    <span class="hljs-keyword">if</span> (!<span class="hljs-title function_">hasOwn</span>(parent, key)) &#123;<br>      <span class="hljs-title function_">mergeField</span>(key)<br>    &#125;<br>  &#125;<br>  <span class="hljs-keyword">function</span> <span class="hljs-title function_">mergeField</span> (key) &#123;<br>    <span class="hljs-comment">/*</span><br><span class="hljs-comment">      starts和defaultStrat，这两个变量存放的合并策略</span><br><span class="hljs-comment">      defaultStrat的逻辑是如果child上存在该属性，则取child上的属性值，如果</span><br><span class="hljs-comment">      没有，则取parent上的该属性值</span><br><span class="hljs-comment">      strats中存放的合并策略较多，不在此函数中讲，下面单讲</span><br><span class="hljs-comment">    */</span><br>    <span class="hljs-keyword">const</span> strat = strats[key] || defaultStrat<br>    options[key] = <span class="hljs-title function_">strat</span>(parent[key], child[key], vm, key)<br>  &#125;<br>  <span class="hljs-keyword">return</span> options<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>starts 中存放的合并策略</p>
</blockquote>
  <img src="/my-blog-template/assets/img/vueSourceCode/init/3.jpg" srcset="/my-blog-template/img/loading.gif" lazyload>

<ul>
<li><p>钩子函数中的合并策略<br>主要是调用 mergeHook 方法 &#x2F;src&#x2F;core&#x2F;util&#x2F;options.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">mergeHook</span> (<br>  <span class="hljs-attr">parentVal</span>: ?<span class="hljs-title class_">Array</span>&lt;<span class="hljs-title class_">Function</span>&gt;,<br>  <span class="hljs-attr">childVal</span>: ?<span class="hljs-title class_">Function</span> | ?<span class="hljs-title class_">Array</span>&lt;<span class="hljs-title class_">Function</span>&gt;<br>): ?<span class="hljs-title class_">Array</span>&lt;<span class="hljs-title class_">Function</span>&gt; &#123;<br>  <span class="hljs-keyword">const</span> res = childVal<br>    ? parentVal<br>      ? parentVal.<span class="hljs-title function_">concat</span>(childVal)<br>      : <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">isArray</span>(childVal)<br>        ? childVal<br>        : [childVal]<br>    : parentVal<br>  <span class="hljs-keyword">return</span> res<br>    ? <span class="hljs-title function_">dedupeHooks</span>(res)<br>    : res<br>&#125;<br></code></pre></td></tr></table></figure>
<p>主要分为四种情况<br>1.child 的 options 不存在该属性，parent 的 options 上存在，返回 parent 上的属性<br>2.child 和 parent 都存在该属性，返回 concat 的属性<br>3.child 上存在，parent 不存在，child 上的属性为数组，返回 child 上的该属性<br>4.child 上存在，parent 不存在，child 上的属性不为数组，将该属性转换为数组返回</p>
</li>
<li><p>props&#x2F;methods&#x2F;inject&#x2F;computed 的策略<br>方法在 &#x2F;src&#x2F;core&#x2F;util&#x2F;options.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript">strats.<span class="hljs-property">props</span> =<br>strats.<span class="hljs-property">methods</span> =<br>strats.<span class="hljs-property">inject</span> =<br>strats.<span class="hljs-property">computed</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params"></span><br><span class="hljs-params">parentVal: ?<span class="hljs-built_in">Object</span>,</span><br><span class="hljs-params">childVal: ?<span class="hljs-built_in">Object</span>,</span><br><span class="hljs-params">vm?: Component,</span><br><span class="hljs-params">key: string</span><br><span class="hljs-params"></span>): ?<span class="hljs-title class_">Object</span> &#123;<br><span class="hljs-keyword">if</span> (childVal &amp;&amp; process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span>) &#123;<br>  <span class="hljs-title function_">assertObjectType</span>(key, childVal, vm)<br>&#125;<br><span class="hljs-keyword">if</span> (!parentVal) <span class="hljs-keyword">return</span> childVal<br><span class="hljs-keyword">const</span> ret = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(<span class="hljs-literal">null</span>)<br><span class="hljs-title function_">extend</span>(ret, parentVal)<br><span class="hljs-keyword">if</span> (childVal) <span class="hljs-title function_">extend</span>(ret, childVal)<br><span class="hljs-keyword">return</span> ret<br>&#125;<br></code></pre></td></tr></table></figure>

<p>1.如果 parent options 上没有该属性，则直接返回 child options 上的该属性 2.如果 parent options 和 child options 都有，则合并 parent options 和 childoptions 并生成一个新的对象。(如果 parent 和 child 上有同名属性，<br>合并后的以 child options 上的为准)</p>
</li>
<li><p>components&#x2F;directives&#x2F;filters 的合并策略<br>方法在 &#x2F;src&#x2F;core&#x2F;util&#x2F;options.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">mergeAssets</span> (<br><span class="hljs-attr">parentVal</span>: ?<span class="hljs-title class_">Object</span>,<br><span class="hljs-attr">childVal</span>: ?<span class="hljs-title class_">Object</span>,<br>vm?: <span class="hljs-title class_">Component</span>,<br><span class="hljs-attr">key</span>: string<br>): <span class="hljs-title class_">Object</span> &#123;<br><span class="hljs-keyword">const</span> res = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(parentVal || <span class="hljs-literal">null</span>)<br><span class="hljs-keyword">if</span> (childVal) &#123;<br>  process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span> &amp;&amp; <span class="hljs-title function_">assertObjectType</span>(key, childVal, vm)<br>  <span class="hljs-keyword">return</span> <span class="hljs-title function_">extend</span>(res, childVal)<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>  <span class="hljs-keyword">return</span> res<br>&#125;<br>&#125;<br><span class="hljs-comment">// ASSET_TYPES =[&#x27;component&#x27;,&#x27;directive&#x27;,&#x27;filter&#x27;]</span><br><span class="hljs-variable constant_">ASSET_TYPES</span>.<span class="hljs-title function_">forEach</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">type</span>) &#123;<br>strats[type + <span class="hljs-string">&#x27;s&#x27;</span>] = mergeAssets<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>这边的合并策略跟上面的类似</p>
</li>
<li><p>data 和 provide 的策略<br>方法在 &#x2F;src&#x2F;core&#x2F;util&#x2F;options.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">mergeDataOrFn</span> (<br>  <span class="hljs-attr">parentVal</span>: any,<br>  <span class="hljs-attr">childVal</span>: any,<br>  vm?: <span class="hljs-title class_">Component</span><br>  ): ?<span class="hljs-title class_">Function</span> &#123;<br>  <span class="hljs-comment">// 如果调用方法的不是vm实例，即通过Vue.extend/Vue.component调用方法的情况</span><br>  <span class="hljs-keyword">if</span> (!vm) &#123;<br>    <span class="hljs-comment">// 该情况下，child和parent的options的data必须是函数</span><br>    <span class="hljs-comment">// 如果child没有值返回parent的，反之返回child的，如果都有值，返回合并的</span><br>    <span class="hljs-keyword">if</span> (!childVal) &#123;<br>      <span class="hljs-keyword">return</span> parentVal<br>    &#125;<br>    <span class="hljs-keyword">if</span> (!parentVal) &#123;<br>      <span class="hljs-keyword">return</span> childVal<br>    &#125;<br>    <span class="hljs-comment">// when parentVal &amp; childVal are both present,</span><br>    <span class="hljs-comment">// we need to return a function that returns the</span><br>    <span class="hljs-comment">// merged result of both functions... no need to</span><br>    <span class="hljs-comment">// check if parentVal is a function here because</span><br>    <span class="hljs-comment">// it has to be a function to pass previous merges.</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">mergedDataFn</span> () &#123;<br>      <span class="hljs-keyword">return</span> <span class="hljs-title function_">mergeData</span>(<br>        <span class="hljs-keyword">typeof</span> childVal === <span class="hljs-string">&#x27;function&#x27;</span> ? childVal.<span class="hljs-title function_">call</span>(<span class="hljs-variable language_">this</span>, <span class="hljs-variable language_">this</span>) : childVal,<br>        <span class="hljs-keyword">typeof</span> parentVal === <span class="hljs-string">&#x27;function&#x27;</span> ? parentVal.<span class="hljs-title function_">call</span>(<span class="hljs-variable language_">this</span>, <span class="hljs-variable language_">this</span>) : parentVal<br>      )<br>    &#125;<br>  &#125; <span class="hljs-keyword">else</span> &#123;<br>    <span class="hljs-comment">// 如果调用mergeOptions的是vm实例，调用new新建Vue实例触发的mergeOptions</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">mergedInstanceDataFn</span> () &#123;<br>      <span class="hljs-comment">// instance merge</span><br>      <span class="hljs-keyword">const</span> instanceData = <span class="hljs-keyword">typeof</span> childVal === <span class="hljs-string">&#x27;function&#x27;</span><br>        ? childVal.<span class="hljs-title function_">call</span>(vm, vm)<br>        : childVal<br>      <span class="hljs-keyword">const</span> defaultData = <span class="hljs-keyword">typeof</span> parentVal === <span class="hljs-string">&#x27;function&#x27;</span><br>        ? parentVal.<span class="hljs-title function_">call</span>(vm, vm)<br>        : parentVal<br>      <span class="hljs-comment">// 如果新建实例是传入的options上有data属性，则返回跟构造函数合并的data</span><br>      <span class="hljs-keyword">if</span> (instanceData) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-title function_">mergeData</span>(instanceData, defaultData)<br>      &#125; <span class="hljs-keyword">else</span> &#123;<br>        <span class="hljs-comment">// 如果没有则返回构造函数的data</span><br>        <span class="hljs-keyword">return</span> defaultData<br>      &#125;<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ul>
<h1 id="initLifecycle"><a href="#initLifecycle" class="headerlink" title="initLifecycle"></a>initLifecycle</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;lifecycle.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initLifecycle</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>) &#123;<br>  <span class="hljs-comment">// 将实例的options也就是mergeOptions后的options赋值给变量options</span><br>  <span class="hljs-keyword">const</span> options = vm.<span class="hljs-property">$options</span><br><br>  <span class="hljs-comment">// locate first non-abstract parent</span><br>  <span class="hljs-comment">// 定位到第一个非抽象的父组件</span><br>  <span class="hljs-keyword">let</span> parent = options.<span class="hljs-property">parent</span><br>  <span class="hljs-comment">// 如果vm的父实例存在并且vm为非抽象组件</span><br>  <span class="hljs-keyword">if</span> (parent &amp;&amp; !options.<span class="hljs-property">abstract</span>) &#123;<br>    <span class="hljs-comment">// 循环判断vm的父实例是否为抽象组件并且父实例的父实例是否存在</span><br>    <span class="hljs-keyword">while</span> (parent.<span class="hljs-property">$options</span>.<span class="hljs-property">abstract</span> &amp;&amp; parent.<span class="hljs-property">$parent</span>) &#123;<br>      parent = parent.<span class="hljs-property">$parent</span><br>    &#125;<br>    <span class="hljs-comment">// 直到找到第一个非抽象组件的父实例，把vm push到该父实例的children</span><br>    parent.<span class="hljs-property">$children</span>.<span class="hljs-title function_">push</span>(vm)<br>  &#125;<br><br>  <span class="hljs-comment">// 将第一个非抽象实例的父组件赋值给vm的$parent属性</span><br>  <span class="hljs-comment">// 指定已创建的已创建的实例的父实例，子实例可以用this.$parent访问父实例</span><br>  <span class="hljs-comment">// 子实例被push进父实例的children中，见上一行代码</span><br>  vm.<span class="hljs-property">$parent</span> = parent<br>  <span class="hljs-comment">// 如果当前vm有parent，则vm的跟为parent的根，否则为自身</span><br>  vm.<span class="hljs-property">$root</span> = parent ? parent.<span class="hljs-property">$root</span> : vm<br>  <span class="hljs-comment">// 当前实例的子组件</span><br>  vm.<span class="hljs-property">$children</span> = []<br>  <span class="hljs-comment">// 存放所有已注册过ref的所有子组件</span><br>  vm.<span class="hljs-property">$refs</span> = &#123;&#125;<br>  <span class="hljs-comment">// 组件实例相应的watcher实例对象</span><br>  vm.<span class="hljs-property">_watcher</span> = <span class="hljs-literal">null</span><br>  <span class="hljs-comment">// keep-alive中的组件状态，是否被激活</span><br>  vm.<span class="hljs-property">_inactive</span> = <span class="hljs-literal">null</span><br>  vm.<span class="hljs-property">_directInactive</span> = <span class="hljs-literal">false</span><br>  <span class="hljs-comment">// 当前组件是否已经挂载</span><br>  vm.<span class="hljs-property">_isMounted</span> = <span class="hljs-literal">false</span><br>  <span class="hljs-comment">// 当前组件是否已经销毁</span><br>  vm.<span class="hljs-property">_isDestroyed</span> = <span class="hljs-literal">false</span><br>  <span class="hljs-comment">// 当前组件是否正在被销毁，处在beforeDestroy和destroyed之间的状态</span><br>  vm.<span class="hljs-property">_isBeingDestroyed</span> = <span class="hljs-literal">false</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="initEvents"><a href="#initEvents" class="headerlink" title="initEvents"></a>initEvents</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;event.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initEvents</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>) &#123;<br>  vm.<span class="hljs-property">_events</span> = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(<span class="hljs-literal">null</span>)<br>  <span class="hljs-comment">// 表示vm上是否存在父组件通过@hook把钩子函数绑定在当前实例上</span><br>  vm.<span class="hljs-property">_hasHookEvent</span> = <span class="hljs-literal">false</span><br>  <span class="hljs-comment">// init parent attached events</span><br>  <span class="hljs-comment">// _parentListeners表示是否存在父组件绑定在当前实例上的事件(v-on事件)</span><br>  <span class="hljs-keyword">const</span> listeners = vm.<span class="hljs-property">$options</span>.<span class="hljs-property">_parentListeners</span><br>  <span class="hljs-comment">// 如果存在执行updateComponentListeners方法</span><br>  <span class="hljs-keyword">if</span> (listeners) &#123;<br>    <span class="hljs-title function_">updateComponentListeners</span>(vm, listeners)<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>updateComponentListeners</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">updateComponentListeners</span> (<br>  <span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>,<br>  <span class="hljs-attr">listeners</span>: <span class="hljs-title class_">Object</span>,<br>  <span class="hljs-attr">oldListeners</span>: ?<span class="hljs-title class_">Object</span><br>) &#123;<br>  target = vm<br>  <span class="hljs-title function_">updateListeners</span>(listeners, oldListeners || &#123;&#125;, add, remove, createOnceHandler, vm)<br>  target = <span class="hljs-literal">undefined</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p>该函数主要是为了保留对 vm 的引用，并且能在 updateListeners 执行时访问到 vm 实例<br>并执行 add 和 remove 方法</p>
<ul>
<li>updateListeners<blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;vdom&#x2F;helpers&#x2F;update-listeners.js</p>
</blockquote>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">updateListeners</span> (<br>  <span class="hljs-attr">on</span>: <span class="hljs-title class_">Object</span>, <span class="hljs-comment">// 传进来的listeners，也就是父组件绑定在该组件上的事件</span><br>  <span class="hljs-attr">oldOn</span>: <span class="hljs-title class_">Object</span>, <span class="hljs-comment">// 表示该组件上的绑定的旧事件</span><br>  <span class="hljs-attr">add</span>: <span class="hljs-title class_">Function</span>,<br>  <span class="hljs-attr">remove</span>: <span class="hljs-title class_">Function</span>,<br>  <span class="hljs-attr">createOnceHandler</span>: <span class="hljs-title class_">Function</span>,<br>  <span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span><br>) &#123;<br>  <span class="hljs-keyword">let</span> name, def, cur, old, event<br>  <span class="hljs-comment">// 遍历listeners</span><br>  <span class="hljs-keyword">for</span> (name <span class="hljs-keyword">in</span> on) &#123;<br>    def = cur = on[name]<br>    old = oldOn[name]<br>    event = <span class="hljs-title function_">normalizeEvent</span>(name)<br>    <span class="hljs-comment">/* istanbul ignore if */</span><br>    <span class="hljs-keyword">if</span> (__WEEX__ &amp;&amp; <span class="hljs-title function_">isPlainObject</span>(def)) &#123;<br>      cur = def.<span class="hljs-property">handler</span><br>      event.<span class="hljs-property">params</span> = def.<span class="hljs-property">params</span><br>    &#125;<br>    <span class="hljs-comment">// 开发环境如果listeners中的事件是undefined或者null，则提示</span><br>    <span class="hljs-keyword">if</span> (<span class="hljs-title function_">isUndef</span>(cur)) &#123;<br>      process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span> &amp;&amp; <span class="hljs-title function_">warn</span>(<br>        <span class="hljs-string">`Invalid handler for event &quot;<span class="hljs-subst">$&#123;event.name&#125;</span>&quot;: got `</span> + <span class="hljs-title class_">String</span>(cur),<br>        vm<br>      )<br>      <span class="hljs-comment">// 如果旧事件为undefined或null</span><br>    &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-title function_">isUndef</span>(old)) &#123;<br>      <span class="hljs-comment">// fns为cur事件对应的所有回调函数，如果不为空则执行createFnInvoker</span><br>      <span class="hljs-keyword">if</span> (<span class="hljs-title function_">isUndef</span>(cur.<span class="hljs-property">fns</span>)) &#123;<br>        cur = on[name] = <span class="hljs-title function_">createFnInvoker</span>(cur, vm)<br>      &#125;<br>      <span class="hljs-comment">// 判断事件名是否以~开头，是则执行createOnceHandler</span><br>      <span class="hljs-keyword">if</span> (<span class="hljs-title function_">isTrue</span>(event.<span class="hljs-property">once</span>)) &#123;<br>        cur = on[name] = <span class="hljs-title function_">createOnceHandler</span>(event.<span class="hljs-property">name</span>, cur, event.<span class="hljs-property">capture</span>)<br>      &#125;<br>      <span class="hljs-comment">// 如果oldOn中不存在该方法，则调用add注册新方法</span><br>      <span class="hljs-title function_">add</span>(event.<span class="hljs-property">name</span>, cur, event.<span class="hljs-property">capture</span>, event.<span class="hljs-property">passive</span>, event.<span class="hljs-property">params</span>)<br>    <span class="hljs-comment">// 如果cur和old都存在，并且cur不等于old</span><br>    &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (cur !== old) &#123;<br>      <span class="hljs-comment">// 将当前事件赋值给旧事件</span><br>      old.<span class="hljs-property">fns</span> = cur<br>      <span class="hljs-comment">// 再将旧事件赋值给on上对应的事件</span><br>      on[name] = old<br>    &#125;<br>  &#125;<br>  <span class="hljs-comment">// 遍历旧事件</span><br>  <span class="hljs-keyword">for</span> (name <span class="hljs-keyword">in</span> oldOn) &#123;<br>    <span class="hljs-comment">// 如果新事件内没有旧事件内的方法，remove解绑该事件，也就是调用$off</span><br>    <span class="hljs-keyword">if</span> (<span class="hljs-title function_">isUndef</span>(on[name])) &#123;<br>      event = <span class="hljs-title function_">normalizeEvent</span>(name)<br>      <span class="hljs-title function_">remove</span>(event.<span class="hljs-property">name</span>, oldOn[name], event.<span class="hljs-property">capture</span>)<br>    &#125;<br>  &#125;<br>&#125;<br><br><span class="hljs-comment">// add函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">add</span> (event, fn) &#123;<br>  target.$on(event, fn)<br>&#125;<br><span class="hljs-comment">// $on函数</span><br><span class="hljs-title class_">Vue</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">$on</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">event: string | <span class="hljs-built_in">Array</span>&lt;string&gt;, fn: <span class="hljs-built_in">Function</span></span>): <span class="hljs-title class_">Component</span> &#123;<br>    <span class="hljs-keyword">const</span> <span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span> = <span class="hljs-variable language_">this</span><br>    <span class="hljs-comment">// 如果event为数组，进入递归，将数组中的每个方法都拎出来存到_events对象中</span><br>    <span class="hljs-keyword">if</span> (<span class="hljs-title class_">Array</span>.<span class="hljs-title function_">isArray</span>(event)) &#123;<br>      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>, l = event.<span class="hljs-property">length</span>; i &lt; l; i++) &#123;<br>        vm.$on(event[i], fn)<br>      &#125;<br>    &#125; <span class="hljs-keyword">else</span> &#123;<br>      <span class="hljs-comment">// 将方法存到_events对象中，事件名对应方法</span><br>      (vm.<span class="hljs-property">_events</span>[event] || (vm.<span class="hljs-property">_events</span>[event] = [])).<span class="hljs-title function_">push</span>(fn)<br>      <span class="hljs-comment">// optimize hook:event cost by using a boolean flag marked at registration</span><br>      <span class="hljs-comment">// instead of a hash lookup</span><br>      <span class="hljs-keyword">if</span> (hookRE.<span class="hljs-title function_">test</span>(event)) &#123;<br>        vm.<span class="hljs-property">_hasHookEvent</span> = <span class="hljs-literal">true</span><br>      &#125;<br>    &#125;<br>    <span class="hljs-keyword">return</span> vm<br>  &#125;<br><br><span class="hljs-comment">// remove函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">remove</span> (event, fn) &#123;<br>  target.$off(event, fn)<br>&#125;<br><br><span class="hljs-comment">// createOnceHandler函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">createOnceHandler</span> (event, fn) &#123;<br>  <span class="hljs-keyword">const</span> _target = target<br>  <span class="hljs-keyword">return</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">onceHandler</span> () &#123;<br>    <span class="hljs-keyword">const</span> res = fn.<span class="hljs-title function_">apply</span>(<span class="hljs-literal">null</span>, <span class="hljs-variable language_">arguments</span>)<br>    <span class="hljs-keyword">if</span> (res !== <span class="hljs-literal">null</span>) &#123;<br>      _target.$off(event, onceHandler)<br>    &#125;<br>  &#125;<br>&#125;<br><span class="hljs-comment">// 上述两个函数都用到的$off方法，销毁_events对象中的相应事件</span><br><span class="hljs-title class_">Vue</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">$off</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">event?: string | <span class="hljs-built_in">Array</span>&lt;string&gt;, fn?: <span class="hljs-built_in">Function</span></span>): <span class="hljs-title class_">Component</span> &#123;<br>  <span class="hljs-keyword">const</span> <span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span> = <span class="hljs-variable language_">this</span><br>  <span class="hljs-comment">// all</span><br>  <span class="hljs-keyword">if</span> (!<span class="hljs-variable language_">arguments</span>.<span class="hljs-property">length</span>) &#123;<br>    vm.<span class="hljs-property">_events</span> = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(<span class="hljs-literal">null</span>)<br>    <span class="hljs-keyword">return</span> vm<br>  &#125;<br>  <span class="hljs-comment">// array of events</span><br>  <span class="hljs-comment">// 如果event是数组，递归调用$off销毁事件</span><br>  <span class="hljs-keyword">if</span> (<span class="hljs-title class_">Array</span>.<span class="hljs-title function_">isArray</span>(event)) &#123;<br>    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>, l = event.<span class="hljs-property">length</span>; i &lt; l; i++) &#123;<br>      vm.$off(event[i], fn)<br>    &#125;<br>    <span class="hljs-keyword">return</span> vm<br>  &#125;<br>  <span class="hljs-comment">// specific event</span><br>  <span class="hljs-keyword">const</span> cbs = vm.<span class="hljs-property">_events</span>[event]<br>  <span class="hljs-keyword">if</span> (!cbs) &#123;<br>    <span class="hljs-keyword">return</span> vm<br>  &#125;<br>  <span class="hljs-keyword">if</span> (!fn) &#123;<br>    vm.<span class="hljs-property">_events</span>[event] = <span class="hljs-literal">null</span><br>    <span class="hljs-keyword">return</span> vm<br>  &#125;<br>  <span class="hljs-comment">// specific handler</span><br>  <span class="hljs-keyword">let</span> cb<br>  <span class="hljs-keyword">let</span> i = cbs.<span class="hljs-property">length</span><br>  <span class="hljs-keyword">while</span> (i--) &#123;<br>    cb = cbs[i]<br>    <span class="hljs-keyword">if</span> (cb === fn || cb.<span class="hljs-property">fn</span> === fn) &#123;<br>      cbs.<span class="hljs-title function_">splice</span>(i, <span class="hljs-number">1</span>)<br>      <span class="hljs-keyword">break</span><br>    &#125;<br>  &#125;<br>  <span class="hljs-keyword">return</span> vm<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="initRender"><a href="#initRender" class="headerlink" title="initRender"></a>initRender</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initRender</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>) &#123;<br>  <span class="hljs-comment">// _vnode组件的真实节点，tag为template下的第一个节点</span><br>  vm.<span class="hljs-property">_vnode</span> = <span class="hljs-literal">null</span> <span class="hljs-comment">// the root of the child tree</span><br>  vm.<span class="hljs-property">_staticTrees</span> = <span class="hljs-literal">null</span> <span class="hljs-comment">// v-once cached trees</span><br>  <span class="hljs-keyword">const</span> options = vm.<span class="hljs-property">$options</span><br>  <span class="hljs-comment">// parentVnode，$vnode父组件中的占位符节点</span><br>  <span class="hljs-keyword">const</span> parentVnode = vm.<span class="hljs-property">$vnode</span> = options.<span class="hljs-property">_parentVnode</span> <span class="hljs-comment">// the placeholder node in parent tree</span><br>  <span class="hljs-comment">// renderContext 父组件的vNode 等同于子组件的$parent</span><br>  <span class="hljs-keyword">const</span> renderContext = parentVnode &amp;&amp; parentVnode.<span class="hljs-property">context</span><br>  <span class="hljs-comment">// 储存父组件传来的slot</span><br>  vm.<span class="hljs-property">$slots</span> = <span class="hljs-title function_">resolveSlots</span>(options.<span class="hljs-property">_renderChildren</span>, renderContext)<br>  <span class="hljs-comment">// 将$scopedSlots冻结，置为空</span><br>  vm.<span class="hljs-property">$scopedSlots</span> = emptyObject<br>  <span class="hljs-comment">// bind the createElement fn to this instance</span><br>  <span class="hljs-comment">// so that we get proper render context inside it.</span><br>  <span class="hljs-comment">// args order: tag, data, children, normalizationType, alwaysNormalize</span><br>  <span class="hljs-comment">// internal version is used by render functions compiled from templates</span><br>  <span class="hljs-comment">// 赋值创建_c和$createElement函数，都是生成VNode的方法</span><br>  vm.<span class="hljs-property">_c</span> = <span class="hljs-function">(<span class="hljs-params">a, b, c, d</span>) =&gt;</span> <span class="hljs-title function_">createElement</span>(vm, a, b, c, d, <span class="hljs-literal">false</span>)<br>  <span class="hljs-comment">// normalization is always applied for the public version, used in</span><br>  <span class="hljs-comment">// user-written render functions.</span><br>  vm.<span class="hljs-property">$createElement</span> = <span class="hljs-function">(<span class="hljs-params">a, b, c, d</span>) =&gt;</span> <span class="hljs-title function_">createElement</span>(vm, a, b, c, d, <span class="hljs-literal">true</span>)<br><br>  <span class="hljs-comment">// $attrs &amp; $listeners are exposed for easier HOC creation.</span><br>  <span class="hljs-comment">// they need to be reactive so that HOCs using them are always updated</span><br>  <span class="hljs-keyword">const</span> parentData = parentVnode &amp;&amp; parentVnode.<span class="hljs-property">data</span><br><br>  <span class="hljs-comment">/* istanbul ignore else */</span><br>  <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span>) &#123;<br>    <span class="hljs-title function_">defineReactive</span>(vm, <span class="hljs-string">&#x27;$attrs&#x27;</span>, parentData &amp;&amp; parentData.<span class="hljs-property">attrs</span> || emptyObject, <span class="hljs-function">() =&gt;</span> &#123;<br>      !isUpdatingChildComponent &amp;&amp; <span class="hljs-title function_">warn</span>(<span class="hljs-string">`$attrs is readonly.`</span>, vm)<br>    &#125;, <span class="hljs-literal">true</span>)<br>    <span class="hljs-title function_">defineReactive</span>(vm, <span class="hljs-string">&#x27;$listeners&#x27;</span>, options.<span class="hljs-property">_parentListeners</span> || emptyObject, <span class="hljs-function">() =&gt;</span> &#123;<br>      !isUpdatingChildComponent &amp;&amp; <span class="hljs-title function_">warn</span>(<span class="hljs-string">`$listeners is readonly.`</span>, vm)<br>    &#125;, <span class="hljs-literal">true</span>)<br>  &#125; <span class="hljs-keyword">else</span> &#123;<br>    <span class="hljs-title function_">defineReactive</span>(vm, <span class="hljs-string">&#x27;$attrs&#x27;</span>, parentData &amp;&amp; parentData.<span class="hljs-property">attrs</span> || emptyObject, <span class="hljs-literal">null</span>, <span class="hljs-literal">true</span>)<br>    <span class="hljs-title function_">defineReactive</span>(vm, <span class="hljs-string">&#x27;$listeners&#x27;</span>, options.<span class="hljs-property">_parentListeners</span> || emptyObject, <span class="hljs-literal">null</span>, <span class="hljs-literal">true</span>)<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="initInjections"><a href="#initInjections" class="headerlink" title="initInjections"></a>initInjections</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;inject.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-comment">// 初始化inject配置项</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initInjections</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>) &#123;<br>  <span class="hljs-comment">// 解析inject配置项，将vm inject配置项中的每一个key对应的val生成result[key] = val的形式，最终赋值给result</span><br>  <span class="hljs-keyword">const</span> result = <span class="hljs-title function_">resolveInject</span>(vm.<span class="hljs-property">$options</span>.<span class="hljs-property">inject</span>, vm)<br>  <span class="hljs-comment">// 对result做响应式处理，不建议子组件更改这些数据，因为父组件中的provide发生更改，子组件中的更改将会被覆盖</span><br>  <span class="hljs-keyword">if</span> (result) &#123;<br>    <span class="hljs-title function_">toggleObserving</span>(<span class="hljs-literal">false</span>)<br>    <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(result).<span class="hljs-title function_">forEach</span>(<span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> &#123;<br>      <span class="hljs-comment">/* istanbul ignore else */</span><br>      <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span>) &#123;<br>        <span class="hljs-title function_">defineReactive</span>(vm, key, result[key], <span class="hljs-function">() =&gt;</span> &#123;<br>          <span class="hljs-title function_">warn</span>(<br>            <span class="hljs-string">`Avoid mutating an injected value directly since the changes will be `</span> +<br>            <span class="hljs-string">`overwritten whenever the provided component re-renders. `</span> +<br>            <span class="hljs-string">`injection being mutated: &quot;<span class="hljs-subst">$&#123;key&#125;</span>&quot;`</span>,<br>            vm<br>          )<br>        &#125;)<br>      &#125; <span class="hljs-keyword">else</span> &#123;<br>        <span class="hljs-title function_">defineReactive</span>(vm, key, result[key])<br>      &#125;<br>    &#125;)<br>    <span class="hljs-title function_">toggleObserving</span>(<span class="hljs-literal">true</span>)<br>  &#125;<br>&#125;<br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">resolveInject</span> (<span class="hljs-attr">inject</span>: any, <span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>): ?<span class="hljs-title class_">Object</span> &#123;<br>  <span class="hljs-keyword">if</span> (inject) &#123;<br>    <span class="hljs-comment">/*</span><br><span class="hljs-comment">      inject的形式为</span><br><span class="hljs-comment">      inject = &#123;</span><br><span class="hljs-comment">        key: &#123;</span><br><span class="hljs-comment">          from: provideKey,</span><br><span class="hljs-comment">          default: xxx</span><br><span class="hljs-comment">        &#125;</span><br><span class="hljs-comment">      &#125;</span><br><span class="hljs-comment">    */</span><br>    <span class="hljs-comment">// inject is :any because flow is not smart enough to figure out cached</span><br>    <span class="hljs-keyword">const</span> result = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(<span class="hljs-literal">null</span>)<br>    <span class="hljs-comment">// 拿到inject中所有的key</span><br>    <span class="hljs-keyword">const</span> keys = hasSymbol<br>      ? <span class="hljs-title class_">Reflect</span>.<span class="hljs-title function_">ownKeys</span>(inject)<br>      : <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(inject)<br>    <span class="hljs-comment">// 遍历keys</span><br>    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; keys.<span class="hljs-property">length</span>; i++) &#123;<br>      <span class="hljs-keyword">const</span> key = keys[i]<br>      <span class="hljs-comment">// #6574 in case the inject object is observed...</span><br>      <span class="hljs-comment">// 跳过__ob__</span><br>      <span class="hljs-keyword">if</span> (key === <span class="hljs-string">&#x27;__ob__&#x27;</span>) <span class="hljs-keyword">continue</span><br>      <span class="hljs-comment">// 拿到provide中对应的key</span><br>      <span class="hljs-keyword">const</span> provideKey = inject[key].<span class="hljs-property">from</span><br>      <span class="hljs-comment">// 遍历组件直至根组件，拿到所有result[key]对应的provideKey</span><br>      <span class="hljs-keyword">let</span> source = vm<br>      <span class="hljs-keyword">while</span> (source) &#123;<br>        <span class="hljs-keyword">if</span> (source.<span class="hljs-property">_provided</span> &amp;&amp; <span class="hljs-title function_">hasOwn</span>(source.<span class="hljs-property">_provided</span>, provideKey)) &#123;<br>          result[key] = source.<span class="hljs-property">_provided</span>[provideKey]<br>          <span class="hljs-keyword">break</span><br>        &#125;<br>        source = source.<span class="hljs-property">$parent</span><br>      &#125;<br>      <span class="hljs-comment">// 如果循环遍历没找到，则去inject中的default值</span><br>      <span class="hljs-keyword">if</span> (!source) &#123;<br>        <span class="hljs-keyword">if</span> (<span class="hljs-string">&#x27;default&#x27;</span> <span class="hljs-keyword">in</span> inject[key]) &#123;<br>          <span class="hljs-keyword">const</span> provideDefault = inject[key].<span class="hljs-property">default</span><br>          result[key] = <span class="hljs-keyword">typeof</span> provideDefault === <span class="hljs-string">&#x27;function&#x27;</span><br>            ? provideDefault.<span class="hljs-title function_">call</span>(vm)<br>            : provideDefault<br>        &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (process.<span class="hljs-property">env</span>.<span class="hljs-property">NODE_ENV</span> !== <span class="hljs-string">&#x27;production&#x27;</span>) &#123;<br>          <span class="hljs-title function_">warn</span>(<span class="hljs-string">`Injection &quot;<span class="hljs-subst">$&#123;key&#125;</span>&quot; not found`</span>, vm)<br>        &#125;<br>      &#125;<br>    &#125;<br>    <span class="hljs-keyword">return</span> result<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="initState"><a href="#initState" class="headerlink" title="initState"></a>initState</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;state.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-comment">// 响应式原理 处理props data methods computed watch 详情见下一篇</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initState</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>) &#123;<br>  vm.<span class="hljs-property">_watchers</span> = []<br>  <span class="hljs-keyword">const</span> opts = vm.<span class="hljs-property">$options</span><br>  <span class="hljs-keyword">if</span> (opts.<span class="hljs-property">props</span>) <span class="hljs-title function_">initProps</span>(vm, opts.<span class="hljs-property">props</span>)<br>  <span class="hljs-keyword">if</span> (opts.<span class="hljs-property">methods</span>) <span class="hljs-title function_">initMethods</span>(vm, opts.<span class="hljs-property">methods</span>)<br>  <span class="hljs-keyword">if</span> (opts.<span class="hljs-property">data</span>) &#123;<br>    <span class="hljs-title function_">initData</span>(vm)<br>  &#125; <span class="hljs-keyword">else</span> &#123;<br>    <span class="hljs-title function_">observe</span>(vm.<span class="hljs-property">_data</span> = &#123;&#125;, <span class="hljs-literal">true</span> <span class="hljs-comment">/* asRootData */</span>)<br>  &#125;<br>  <span class="hljs-keyword">if</span> (opts.<span class="hljs-property">computed</span>) <span class="hljs-title function_">initComputed</span>(vm, opts.<span class="hljs-property">computed</span>)<br>  <span class="hljs-keyword">if</span> (opts.<span class="hljs-property">watch</span> &amp;&amp; opts.<span class="hljs-property">watch</span> !== nativeWatch) &#123;<br>    <span class="hljs-title function_">initWatch</span>(vm, opts.<span class="hljs-property">watch</span>)<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="initProvide"><a href="#initProvide" class="headerlink" title="initProvide"></a>initProvide</h1><blockquote>
<p>目录 &#x2F;src&#x2F;core&#x2F;instance&#x2F;inject.js</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs JavaScript"><span class="hljs-comment">// 解析组件配置项上的provide对象，将其挂载到vm的_provided属性上</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">initProvide</span> (<span class="hljs-attr">vm</span>: <span class="hljs-title class_">Component</span>) &#123;<br>  <span class="hljs-keyword">const</span> provide = vm.<span class="hljs-property">$options</span>.<span class="hljs-property">provide</span><br>  <span class="hljs-keyword">if</span> (provide) &#123;<br>    vm.<span class="hljs-property">_provided</span> = <span class="hljs-keyword">typeof</span> provide === <span class="hljs-string">&#x27;function&#x27;</span><br>      ? provide.<span class="hljs-title function_">call</span>(vm)<br>      : provide<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>Vue 的初始化过程（new Vue(options)）做了些什么？</p>
<p>new Vue(options)通过调用 vue.prototype_init 处理组件配置项<br>初始化根组件时通过 resolveConstructorOptions 进行选项合并操作，将全局配置合并到根组件的局部配置上<br>初始化子组件通过 initInternalComponent，将组件配置对象上的一些深层次属性放到 vm.$options 选项中，以提高代码的执行效率<br>initLifecycle初始化组件实例的关系属性，比如 $parent、$children、$root、$refs 等<br>initEvents 处理自定义事件<br>调用 beforeCreate 钩子函数<br>initInjections 初始化组件的 inject 配置项，得到 ret[key] &#x3D; val 形式的配置对象，然后对该配置对象进行浅层的响应式处理（只处理了对象第一层数据），并代理每个 key 到 vm 实例上<br>initState 数据响应式，处理 props、methods、data、computed、watch 等选项<br>initProvide 解析组件配置项上的 provide 对象，将其挂载到 vm._provided 属性上<br>调用 created 钩子函数<br>如果发现配置项上有 el 选项，则自动调用 $mount 方法，也就是说有 el 选项，就不需要再手动调用 $mount 方法<br>接下来则进入挂载阶段</p>


              </div>

            <hr/>
            <div>
              <div class="post-metas my-3">

    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>


<span class="category-chains">



      <span class="category-chain">

  <a href="/my-blog-template/categories/%E6%BA%90%E7%A0%81/" class="category-chain-item">源码</a>



      </span>


</span>

    </div>


    <div class="post-meta">
      <i class="iconfont icon-tags"></i>

        <a href="/my-blog-template/tags/%E5%AD%A6%E4%B9%A0/">#学习</a>

    </div>

</div>





  <div class="license-box my-3">
    <div class="license-title">
      <div>Vue源码理解-初始化</div>
      <div>https://jiachengh.gitee.io/my-blog-template/2022/01/28/Vue-source-code-init/</div>
    </div>
    <div class="license-meta">

        <div class="license-meta-item">
          <div>作者</div>
          <div>CV Man</div>
        </div>


        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年1月28日</div>
        </div>



        <div class="license-meta-item">
          <div>许可协议</div>
          <div>



                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>


          </div>
        </div>

    </div>
    <div class="license-icon iconfont"></div>
  </div>




                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">


                      <a href="/my-blog-template/2022/01/28/nextTick/" title="Vue中nextTick原理">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Vue中nextTick原理</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>

                  </article>
                  <article class="post-next col-6">


                      <a href="/my-blog-template/2020/12/28/EventLoop/" title="EventLoop事件循环">
                        <span class="hidden-mobile">EventLoop事件循环</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>

                  </article>
                </div>

            </div>


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">

  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>
































      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>



      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>




  </main>

  <footer>
    <div class="footer-inner">

    <div class="footer-content">
       <div>©2020 - 2023 By CV Man</div> <div>CV is the Best !</div>
    </div>




</div>

  </footer>

  <!-- Scripts -->

  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/my-blog-template/js/events.js" ></script>
<script  src="/my-blog-template/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');

        typing(text);

    })(window, document);
  </script>





    <script  src="/my-blog-template/js/img-lazyload.js" ></script>






<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>



<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>



<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/my-blog-template/js/local-search.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/my-blog-template/js/boot.js" ></script>




  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
